﻿#ifndef AUDIOPLAYER_H
#define AUDIOPLAYER_H

#include <QThread>

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QAudioSource>
#include <QAudioSink>
#else
#include <QAudioFormat>
#include <QAudioOutput>
#endif

#include <QIODevice>
#include <QSemaphore>
#include <QTimer>
#include "ISynchronizer.h"
#include "Decoder.h"
#include <mutex>

class AudioPlayer : public ISynchronizer
{
    Q_OBJECT

    Q_PROPERTY(Decoder* decoder READ decoder WRITE setDecoder NOTIFY decoderChanged FINAL)

    Q_INTERFACES(ISynchronizer)

public:
    AudioPlayer(QObject* parent = nullptr);

    ~AudioPlayer();

    void start() override;

    void stop() override;

    double clock() override;

    bool isPausing() override;

    void pause() override;

    void resume() override;

    void setMaxDuration(double maxDuration) override {}

    // 跳转到指定时间点
    void seek(double timepoint) override;

    void setPresentSpeed(double speed) override;

    Q_INVOKABLE DecodecSerial presentSerial();

    Q_INVOKABLE double volume() const;

    Q_INVOKABLE void setVolume(double newVolume);

    double presentSpeed() override
        { return m_presentSpeed.load() / 1000000.0; }

    Decoder *decoder();

    void setDecoder(Decoder *newDecoder);

signals:
    void decoderChanged();

protected:
    void run();

private:

    void updateExpired();

    QThread* m_td = nullptr;
    QSemaphore m_initSema;

    DecodecSerial m_presentSerial;
    std::mutex m_presentSerialMutex;

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    QAudioSink* audioSink = nullptr;
#else
    QAudioOutput* audioSink = nullptr;
#endif
    
    QIODevice* audioDevice = nullptr;
    AVFrame* m_curFrame = nullptr;
    qsizetype m_curDataPos = 0;

    std::atomic_uint64_t m_expired;
    std::atomic_bool m_isPaused = false;
    std::atomic_int32_t m_presentSpeed = 1000000;

    Decoder *m_decoder = nullptr;
};

#endif // AUDIOPLAYER_H
